#!/bin/bash
# 建议此脚本在CentOS 7及全新系统中使用
# 优化后的脚本，支持多次运行，不会报错，输出详细日志，对文件操作进行判断

# 开启xtrace和errexit，方便调试和确保脚本在出错时退出
set -xe


# 引入包含check_pip_source函数的脚本
source ./check_pip_source.sh


# 定义日志文件
LOG_FILE="/var/log/system_init.log"
exec > $LOG_FILE 2>&1

echo "开始执行脚本，日志将记录在 $LOG_FILE" 

# 检查是否为root用户
if [[ $(id -u) != "0" ]]; then
    echo "Error: 请使用root用户运行此脚本" 
    exit 1
fi

PIP_SOURCE=check_pip_source
# 调用函数
if PIP_SOURCE; then
    echo "找到可用的pip源:${PIP_SOURCE}"
else
    echo "找不到合适的pip源，请检查网络"
	exit 1
fi



# 定义变量
echo "----------- start 定义变量 ----------------" 
MY_YUMING="grgold.cn"
SERVER_IDC_NUM='IDC_01'
SERVER_PHY_NUM=01
VM_NAME='base-server'
ADMIN_EMAIL='dengjs@grgold.cn'
SMTP_FROM='1106359626@qq.com'
SMTP_PASSWD=''  # 注意：这里需要填写正确的SMTP授权码
SMTP_SERVER='smtps://smtp.qq.com:465'
SMTP_USER='1106359626@qq.com'

# 读取命令行参数
INTERACTIVE_MODE=false
while getopts ":i:p:v:y:l:d:t" option; do
    case $option in
        i) SERVER_IDC_NUM=$OPTARG ;;
        p) SERVER_PHY_NUM=$OPTARG ;;
        v) VM_NAME=$OPTARG ;;
        y) MY_YUMING=$OPTARG ;;
        l) SMTP_PASSWD=$OPTARG ;;
        d) ADMIN_EMAIL=$OPTARG ;;
        t) INTERACTIVE_MODE=true ;;
        *) echo "无效的参数 $OPTARG"  ;;
    esac
done

# 如果启用了交互模式，则进行交互式输入参数
if [ "$INTERACTIVE_MODE" = true ]; then
    echo "----------- start 交互式输入参数 ----------------" 
    read -p "请输入服务器IDC编号 (默认: $SERVER_IDC_NUM): " input_idc
    input_idc=${input_idc:-$SERVER_IDC_NUM}
    SERVER_IDC_NUM=$input_idc

    read -p "请输入服务器物理编号 (默认: $SERVER_PHY_NUM): " input_phy
    input_phy=${input_phy:-$SERVER_PHY_NUM}
    SERVER_PHY_NUM=$input_phy

    read -p "请输入虚拟机名称 (默认: $VM_NAME): " input_vmname
    input_vmname=${input_vmname:-$VM_NAME}
    VM_NAME=$input_vmname

    read -p "请输入域名 (默认: $MY_YUMING): " input_yuming
    input_yuming=${input_yuming:-$MY_YUMING}
    MY_YUMING=$input_yuming

    read -p "请输入管理员邮箱 (默认: $ADMIN_EMAIL): " input_email
    input_email=${input_email:-$ADMIN_EMAIL}
    ADMIN_EMAIL=$input_email

    read -sp "请输入SMTP密码 (默认隐藏): " input_passwd
    input_passwd=${input_passwd:-$SMTP_PASSWD}
    SMTP_PASSWD=$input_passwd

    echo "----------- end 交互式输入参数 ----------------" 
fi


# 输出读取的参数
echo "读取的参数" 
echo "域名: $MY_YUMING" 
echo "IDC机房编号: $SERVER_IDC_NUM" 
echo "物理服务器编号: $SERVER_PHY_NUM" 
echo "虚拟机名称: $VM_NAME" 
echo "管理员邮箱: $ADMIN_EMAIL" 
echo "SMTP发件人: $SMTP_FROM" 
echo "SMTP服务器: $SMTP_SERVER" 
echo "SMTP用户: $SMTP_USER" 

# 创建必要的目录
echo "创建必要的目录" 
mkdir -p /data/backups /data/apps /data/docker_storage

# 设置hostname
echo "设置hostname" 
hostnamectl set-hostname "${SERVER_IDC_NUM}.${SERVER_PHY_NUM}.${VM_NAME}.${MY_YUMING}"

# 将变量写入/etc/profile
echo "将变量写入/etc/profile" 
cat >>/etc/profile <<EOF
# 自定义主机名称
export MY_YUMING=${MY_YUMING}
# IDC机房编号
export SERVER_IDC_NUM=${SERVER_IDC_NUM}
# 物理服务器编号
export SERVER_PHY_NUM=${SERVER_PHY_NUM}
# 虚拟机名称
export VM_NAME=${VM_NAME}
# 管理员邮箱
export ADMIN_EMAIL=${ADMIN_EMAIL}

# SMTP配置
export SMTP_FROM=${SMTP_FROM}
export SMTP_PASSWD=${SMTP_PASSWD}
export SMTP_SERVER=${SMTP_SERVER}
export SMTP_USER=${SMTP_USER}
EOF

# 重新加载/etc/profile
echo "重新加载/etc/profile" 
source /etc/profile

# 设置时区并同步时间
echo "设置时区并同步时间" 
timedatectl set-timezone Asia/Shanghai

# 更新系统并安装必要的工具
echo "更新系统并安装必要的工具" 
yum update -y
yum install -y wget  gcc make autoconf vim sysstat net-tools iostat iftop htop unzip nc nmap telnet bc psmisc httpd-tools shc ntpdate dos2unix nmap git ncdu clamav-server clamav-data clamav-update clamav-filesystem clamav clamav-scanner-systemd clamav-devel clamav-lib clamav-server-systemd gcc libffi-devel python3-pip python-devel openssl-devel

# 添加EPEL源
echo "添加EPEL源" 
if [ ! -f /etc/yum.repos.d/CentOS-Base.repo_bak ]; then
    mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo_bak
    wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
    sed -i 's/aliyuncs/aliyun/g' /etc/yum.repos.d/CentOS-Base.repo
else
    echo "EPEL源已备份，跳过此步骤" 
fi

# 清理并更新yum缓存
echo "清理并更新yum缓存" 
yum clean all
yum makecache
yum update -y

# 配置clamav权限
echo "配置clamav权限" 
setsebool -P antivirus_can_scan_system 1
setsebool -P clamd_use_jit 1

# 禁用SELinux
echo "禁用SELinux" 
sed -i '/SELINUX/{s/permissive/disabled/}' /etc/selinux/config

# 关闭防火墙
echo "关闭防火墙" 
if egrep "7.[0-9]" /etc/redhat-release &>/dev/null; then
    systemctl stop firewalld
    systemctl disable firewalld
elif egrep "6.[0-9]" /etc/redhat-release &>/dev/null; then
    service iptables stop
    chkconfig iptables off
fi

# 配置历史命令显示操作时间
echo "配置历史命令显示操作时间" 
if ! grep HISTTIMEFORMAT /etc/bashrc; then
    echo 'export HISTTIMEFORMAT="%F %T `whoami` "' >>/etc/bashrc
else
    echo "HISTTIMEFORMAT已配置，跳过此步骤" 
fi

# 配置SSH超时时间
echo "配置SSH超时时间" 
if ! grep "TMOUT=600" /etc/profile &>/dev/null; then
    echo "export TMOUT=600" >>/etc/profile
else
    echo "TMOUT已配置，跳过此步骤" 
fi

# 创建ssh_banner.sh的软链接
echo "创建ssh_banner.sh的软链接" 
if [ -e /etc/profile.d/ssh_banner.sh ]; then
    echo "/etc/profile.d/ssh_banner.sh已存在,删除旧链接文件" 
    rm -f /etc/profile.d/ssh_banner.sh
fi
ln -s /data/shell/ssh_banner.sh /etc/profile.d/ssh_banner.sh

# 优化SSH配置
echo "优化SSH配置" 
sed -i 's/#GSSAPIAuthentication yes/GSSAPIAuthentication no/' /etc/ssh/sshd_config
sed -i 's/#UseDNS yes/UseDNS no/' /etc/ssh/sshd_config

# 禁止定时任务发送邮件
echo "禁止定时任务发送邮件" 
sed -i 's/^MAILTO=root/MAILTO=""/' /etc/crontab

# 设置最大打开文件数
echo "设置最大打开文件数" 
if ! grep "* soft nofile 65535" /etc/security/limits.conf &>/dev/null; then
    cat >>/etc/security/limits.conf <<EOF
* soft nofile 65535
* hard nofile 65535
EOF
else
    echo "最大打开文件数已配置，跳过此步骤" 
fi

# 系统内核优化
echo "系统内核优化" 
if ! grep "net.ipv4.tcp_syncookies" /etc/sysctl.conf &>/dev/null; then
    cat >>/etc/sysctl.conf <<EOF
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_max_tw_buckets = 20480
net.ipv4.tcp_max_syn_backlog = 20480
net.core.netdev_max_backlog = 262144
net.ipv4.tcp_fin_timeout = 20
EOF
else
    echo "系统内核优化已配置，跳过此步骤" 
fi

# 减少SWAP使用
echo "减少SWAP使用" 
if [ "$(cat /proc/sys/vm/swappiness)" != "0" ]; then
    echo "0" >/proc/sys/vm/swappiness
else
    echo "SWAP使用已优化，跳过此步骤" 
fi

# 安装jq工具
echo "安装jq工具" 
if [ ! -f /usr/bin/jq ]; then
    {
        wget -O jq https://github.com/stedolan/jq/releases/download/jq-1.6/jq-linux64
        chmod +x jq
        mv jq /usr/bin
    } &> /dev/null &
else
    echo "jq工具已安装，跳过此步骤" 
fi

# 安装Docker
echo "安装Docker" 
if ! command -v docker &>/dev/null; then
    yum -y update
    yum -y install yum-utils device-mapper-persistent-data lvm2
    yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
    yum makecache fast
    yum install -y docker-ce
    systemctl enable docker
    systemctl start docker
else
    echo "Docker已安装，跳过此步骤" 
fi

# 生成Docker配置文件
echo "生成Docker配置文件" 
if [ ! -f /etc/docker/daemon.json ]; then
    sudo sh -c 'mkdir -p /etc/docker && cat >/etc/docker/daemon.json <<EOF
{
  "registry-mirrors" : [
"https://hub.docker.com/",
"https://docker.m.daocloud.io",
"https://hub.geekery.cn",
"https://registry.dockermirror.com",
"https://docker.cloudlayer.icu",
"https://func.ink",
"https://docker.awsl9527.cn"
  ],
  "insecure-registries": ["harbor.example.com"],
  "log-driver": "json-file",
  "log-opts": {"max-size":"50m", "max-file":"3"},
  "data-root": "/data/docker_storage"
}
EOF'
else
    echo "Docker配置文件已存在，跳过此步骤" 
fi




# 安装Docker Compose
echo "安装Docker Compose" 
if ! command -v docker-compose &>/dev/null; then
    pip3 install --upgrade pip
    pip3 uninstall cryptography -y
    pip3 install cryptography==3.4.8
    pip3 install docker-compose -i https://pypi.tuna.tsinghua.edu.cn/simple/
else
    echo "Docker Compose已安装，跳过此步骤" 
fi

# 安装trash-cli垃圾回收站
echo "安装trash-cli垃圾回收站" 
if ! command -v trash-put &>/dev/null; then
    pip3 install trash-cli
else
    echo "trash-cli已安装，跳过此步骤" 
fi

# 安装node_exporter
echo "安装node_exporter" 
process_count=$(ps aux | grep node_exporter | grep -v 'grep' | wc -l)
if [ $process_count -eq 0 ]; then
    if [ ! -f /data/apps/node_exporter/node_exporter ]; then
        cp utils/node_exporter-1.2.2.linux-amd64.tar.gz /data/apps
        tar xf /data/apps/node_exporter-1.2.2.linux-amd64.tar.gz -C /data/apps
        mv /data/apps/node_exporter-1.2.2.linux-amd64 /data/apps/node_exporter
        ln -s /data/apps/node_exporter/node_exporter /usr/bin/node_exporter
        which node_exporter
    else
        echo "node_exporter已安装，跳过此步骤" 
    fi
else
    echo "node_exporter已在运行，跳过此步骤" 
fi

# 创建node_exporter服务
echo "创建node_exporter服务" 
if [ ! -f /lib/systemd/system/node_exporter.service ]; then
    cat >/lib/systemd/system/node_exporter.service <<EOF
[Unit]
Description=Node Exporter

[Service]
ExecStart=/data/apps/node_exporter/node_exporter
Restart=on-failure

[Install]
WantedBy=multi-user.target
EOF
    systemctl daemon-reload
    systemctl enable node_exporter && systemctl restart node_exporter
else
    echo "node_exporter服务已存在，跳过此步骤" 
fi

# 配置邮件发送工具
echo "配置邮件发送工具" 
if [ ! -f /etc/mail.rc ]; then
    yum -y remove sendmail postfix
    yum -y install mailx
    cat >/etc/mail.rc <<EOF
set from=${SMTP_FROM}
set nss-config-dir=/root/.certs
set smtp=${SMTP_SERVER}
set smtp-auth-user=${SMTP_USER}
set smtp-auth-password=${SMTP_PASSWD}
set smtp-auth=login
EOF
    mkdir -p /root/.certs
    openssl s_client -connect smtp.qq.com:465 </dev/null 2>/dev/null | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > /root/.certs/qq.crt
    certutil -A -n "GeoTrust Global CA" -t "C,," -d /root/.certs -i /root/.certs/qq.crt
    certutil -A -n "GeoTrust SSL CA" -t "C,," -d /root/.certs -i /root/.certs/qq.crt
    certutil -A -n "GeoTrust SSL CA - G3" -t "Pu,Pu,Pu" -d /root/.certs -i /root/.certs/qq.crt
else
    echo "邮件发送工具已配置，跳过此步骤" 
fi

# 安装Fail2Ban反爆破工具
echo "安装Fail2Ban反爆破工具" 
if ! command -v fail2ban-server &>/dev/null; then
    yum install -y fail2ban
    systemctl enable fail2ban.service
    systemctl start fail2ban.service
    cp settings/fail2ban/jail.local /etc/fail2ban/jail.local
    cp settings/fail2ban/nginx-deny.conf /etc/fail2ban/filter.d/
else
    echo "Fail2Ban已安装，跳过此步骤" 
fi

# 生成备份目录
echo "生成备份目录" 
mkdir -p /data/backups

# 生成定时备份脚本
echo "生成定时备份脚本" 
if [ ! -f /data/shell/backups.sh ]; then
    cat >/data/shell/backups.sh <<'EOF'
#!/bin/bash
# 备份脚本，可以自定义
echo "备份脚本已运行"
EOF
    chmod +x /data/shell/backups.sh
else
    echo "备份脚本已存在，跳过此步骤" 
fi

# 安装Filebeat进行日志收集
echo "安装Filebeat进行日志收集" 
if [ ! -f ./install_filebeat.sh ]; then
    ./install_filebeat.sh ${MY_YUMING}
else
    echo "Filebeat安装脚本不存在，跳过此步骤" 
fi

# 设置定时任务
echo "设置定时任务" 
if [ ! -f /var/spool/cron/$(whoami) ]; then
    touch /var/spool/cron/$(whoami)
fi
if ! grep "trash-empty" /var/spool/cron/$(whoami) &>/dev/null; then
    cat >>/var/spool/cron/$(whoami) <<EOF
# 每周六凌晨1点清理回收站
0 1 * * 6 trash-empty --all-users
# 每周六0点更新系统
0 0 * * 6 yum update -y
# 每天更新clamav病毒库
0 0 * * * freshclam
# 每天凌晨2点扫描病毒，记录日志并发送报告
20 1 * * * clamscan -r -i / -l /var/log/clamav.log
3 3 * * * cat /var/log/clamav.log | mail -v -s "主机：$(hostname)病毒扫描报告" ${ADMIN_EMAIL}
# 每小时同步时间
* 1 * * * ntpdate ntp.aliyun.com >/dev/null 2>&1
# 每5分钟更新运维常用脚本
*/5 * * * * /data/shell/update_force.sh
# 每分钟检测系统资源并报警
*/1 * * * * /data/shell/monitor.sh
# 每周六发送系统体检报告
0 0 * * 6 /data/shell/system_check.sh | mail -v -s "主机：$(hostname)系统体检报告" ${ADMIN_EMAIL}
# 每天清理/var/log目录下的日志
0 2 * * * find /var/log -name '*.log' | xargs -i sudo sh -c 'echo > {}'
# 每天清理Docker资源
1 2 * * * docker system prune -f --filter "until=24h"
EOF
else
    echo "定时任务已配置，跳过此步骤" 
fi

# 拉取运维常用脚本
echo "拉取运维常用脚本" 
if [ ! -f ./pull_scripts.sh ]; then
    ./pull_scripts.sh
else
    echo "运维常用脚本拉取脚本不存在，跳过此步骤" 
fi

# 自定义命令行提示符
echo "自定义命令行提示符" 
if ! grep "PS1=" /etc/bashrc; then
    cp /etc/bashrc /etc/bashrc.bak
    cat >>/etc/bashrc <<'EOF'
PS1="\[\e[31m\]\D{%c}\[\e[0m\]
   \[\e[36m\]\w\[\e[0m\]\n[\[\e[1;43m\]\u\[\e[0m\]@\H]$ "
EOF
else
    echo "命令行提示符已配置，跳过此步骤" 
fi

# 安装shc工具
echo "安装shc工具" 
if [ ! -f /bin/shc ]; then
    tar -xzvf ./utils/shc-3.8.9.tgz
    gcc ./shc-3.8.9/shc-3.8.9.c -o shc
    mv shc /bin/shc
else
    echo "shc工具已安装，跳过此步骤" 
fi

# 编译并保护脚本
echo "编译并保护脚本" 
for script in /data/shell/*.sh; do
    if [ -f "$script" ]; then
        shc -r -f "$script"
        rm -rf "${script}.x.c"
        mv "${script}.x" "$script"
    fi
done

# 初始化完成
echo "初始化完成" 
echo "发送通知邮件给管理员" 
echo "主机：$(hostname) 已初始化成功" | mail -v -s "脚本初始化成功通知，请登录控制台查看" ${ADMIN_EMAIL}